package client

import (
	intrv1 "bbs-micro/api/proto/gen/proto/intr/v1"
	"context"
	"github.com/ecodeclub/ekit/syncx/atomicx"
	"google.golang.org/grpc"
	"math/rand"
)

// @Description  灰度调度
// @Author 代码小学生王木木
// @Date 2024-04-11 16:12

type GreyScaleInteractiveServiceClient struct {
	remote intrv1.InteractiveServiceClient
	local  intrv1.InteractiveServiceClient
	// 怎么控制流量的呢  一个请求过来，如何控制IPC调用 还是RPC调用 ？负载均衡器的流量控制/随机数和阈值控制流量/服务注册与发现的流量控制/令牌桶算法、漏桶算法限流算法/熔断机制的流量控制
	// 用随机数 + 阈值
	threshold *atomicx.Value[int32]
}

func NewGreyScaleInteractiveServiceClient(remote intrv1.InteractiveServiceClient, local intrv1.InteractiveServiceClient) *GreyScaleInteractiveServiceClient {
	return &GreyScaleInteractiveServiceClient{remote: remote, local: local, threshold: atomicx.NewValue[int32]()}
}

func (i GreyScaleInteractiveServiceClient) client() intrv1.InteractiveServiceClient {
	threshold := i.threshold.Load()
	num := rand.Int31n(100)
	if num < threshold {
		return i.remote
	}
	// 默认值 threshold = 0 所以会永远走本地！~ mi a a a a a a o o o ! 啊
	return i.local
}

func (i *GreyScaleInteractiveServiceClient) IncrReadCnt(ctx context.Context, request *intrv1.IncrReadCntRequest, opt ...grpc.CallOption) (*intrv1.IncrReadCntResponse, error) {
	return i.client().IncrReadCnt(ctx, request, opt...)

}

func (i *GreyScaleInteractiveServiceClient) Like(ctx context.Context, request *intrv1.LikeRequest, opt ...grpc.CallOption) (*intrv1.LikeResponse, error) {
	return i.client().Like(ctx, request, opt...)
}

func (i *GreyScaleInteractiveServiceClient) CancelLike(ctx context.Context, request *intrv1.CancelLikeRequest, opt ...grpc.CallOption) (*intrv1.CancelLikeResponse, error) {
	return i.client().CancelLike(ctx, request, opt...)
}

func (g GreyScaleInteractiveServiceClient) CollectArt(ctx context.Context, in *intrv1.CollectArtRequest, opts ...grpc.CallOption) (*intrv1.CollectArtResponse, error) {
	return g.client().CollectArt(ctx, in, opts...)
}

func (i *GreyScaleInteractiveServiceClient) Get(ctx context.Context, request *intrv1.GetRequest, opt ...grpc.CallOption) (*intrv1.GetResponse, error) {
	return i.client().Get(ctx, request, opt...)
}

func (i *GreyScaleInteractiveServiceClient) GetByIds(ctx context.Context, request *intrv1.GetByIdsRequest, opt ...grpc.CallOption) (*intrv1.GetByIdsResponse, error) {
	return i.client().GetByIds(ctx, request, opt...)
}

func (i *GreyScaleInteractiveServiceClient) UpdateThreshold(newThreshold int32) {
	i.threshold.Store(newThreshold)
}
